home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / accum.c next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  10.2 KB  |  361 lines

  1. /* $Id: accum.c,v 1.2 1996/09/15 14:19:44 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.0
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: accum.c,v $
  26.  * Revision 1.2  1996/09/15 14:19:44  brianp
  27.  * now use GLframebuffer and GLvisual
  28.  * added gl_alloc_accum_buffer()
  29.  *
  30.  * Revision 1.1  1996/09/13 01:38:16  brianp
  31.  * Initial revision
  32.  *
  33.  */
  34.  
  35.  
  36. #include <limits.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include "accum.h"
  40. #include "context.h"
  41. #include "dlist.h"
  42. #include "macros.h"
  43. #include "types.h"
  44.  
  45.  
  46.  
  47. void gl_alloc_accum_buffer( GLcontext *ctx )
  48. {
  49.    GLint n;
  50.  
  51.    if (ctx->Buffer->Accum) {
  52.       free( ctx->Buffer->Accum );
  53.       ctx->Buffer->Accum = NULL;
  54.    }
  55.  
  56.    /* allocate accumulation buffer if not already present */
  57.    n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
  58.    ctx->Buffer->Accum = (GLaccum *) malloc( n );
  59.    if (!ctx->Buffer->Accum) {
  60.       /* unable to setup accumulation buffer */
  61.       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
  62.    }
  63. }
  64.  
  65.  
  66.  
  67. void gl_ClearAccum( GLcontext *ctx,
  68.                     GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
  69. {
  70.    if (INSIDE_BEGIN_END(ctx)) {
  71.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  72.       return;
  73.    }
  74.    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
  75.    ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
  76.    ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
  77.    ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
  78. }
  79.  
  80.  
  81.  
  82.  
  83. void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
  84. {
  85.    GLuint xpos, ypos, width, height;
  86.    GLfloat acc_scale;
  87.  
  88.    if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
  89.       /* No accumulation buffer! */
  90.       return;
  91.    }
  92.  
  93.    if (sizeof(GLaccum)==1) {
  94.       acc_scale = 127.0;
  95.    }
  96.    else if (sizeof(GLaccum)==2) {
  97.       acc_scale = 32767.0;
  98.    }
  99.    else {
  100.       /* sizeof(GLaccum) > 2 (Cray) */
  101.       acc_scale = (float) SHRT_MAX;
  102.    }
  103.  
  104.    if (INSIDE_BEGIN_END(ctx)) {
  105.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  106.       return;
  107.    }
  108.  
  109.    /* Determine region to operate upon. */
  110.    if (ctx->Scissor.Enabled) {
  111.       xpos = ctx->Scissor.X;
  112.       ypos = ctx->Scissor.Y;
  113.       width = ctx->Scissor.Width;
  114.       height = ctx->Scissor.Height;
  115.    }
  116.    else {
  117.       /* whole window */
  118.       xpos = 0;
  119.       ypos = 0;
  120.       width = ctx->Buffer->Width;
  121.       height = ctx->Buffer->Height;
  122.    }
  123.  
  124.    switch (op) {
  125.       case GL_ADD:
  126.          {
  127.         GLaccum ival, *acc;
  128.         GLuint i, j;
  129.  
  130.         ival = (GLaccum) (value * acc_scale);
  131.         for (j=0;j<height;j++) {
  132.            acc = ctx->Buffer->Accum
  133.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  134.            for (i=0;i<width;i++) {
  135.           *acc += ival;      acc++;   /* red */
  136.           *acc += ival;      acc++;   /* green */
  137.           *acc += ival;      acc++;   /* blue */
  138.           *acc += ival;      acc++;   /* alpha */
  139.            }
  140.            ypos++;
  141.         }
  142.      }
  143.      break;
  144.       case GL_MULT:
  145.      {
  146.         GLaccum *acc;
  147.         GLuint i, j;
  148.  
  149.         for (j=0;j<height;j++) {
  150.            acc = ctx->Buffer->Accum
  151.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  152.            for (i=0;i<width;i++) {
  153.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*r*/
  154.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  155.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  156.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*a*/
  157.            }
  158.            ypos++;
  159.         }
  160.      }
  161.      break;
  162.       case GL_ACCUM:
  163.      {
  164.         GLaccum *acc;
  165.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  166.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  167.         GLfloat rscale, gscale, bscale, ascale;
  168.         GLuint i, j;
  169.  
  170.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  171.  
  172.         /* Accumulate */
  173.         rscale = value * acc_scale * ctx->Visual->InvRedScale;
  174.         gscale = value * acc_scale * ctx->Visual->InvGreenScale;
  175.         bscale = value * acc_scale * ctx->Visual->InvBlueScale;
  176.         ascale = value * acc_scale * ctx->Visual->InvAlphaScale;
  177.         for (j=0;j<height;j++) {
  178.            (*ctx->Driver.ReadColorSpan)( ctx, width, xpos, ypos,
  179.                                              red, green, blue, alpha);
  180.            acc = ctx->Buffer->Accum
  181.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  182.            for (i=0;i<width;i++) {
  183.           *acc += (GLaccum) ( (GLfloat) red[i]   * rscale );  acc++;
  184.           *acc += (GLaccum) ( (GLfloat) green[i] * gscale );  acc++;
  185.           *acc += (GLaccum) ( (GLfloat) blue[i]  * bscale );  acc++;
  186.           *acc += (GLaccum) ( (GLfloat) alpha[i] * ascale );  acc++;
  187.            }
  188.            ypos++;
  189.         }
  190.  
  191.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  192.      }
  193.      break;
  194.       case GL_LOAD:
  195.      {
  196.         GLaccum *acc;
  197.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  198.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  199.         GLfloat rscale, gscale, bscale, ascale;
  200.         GLuint i, j;
  201.  
  202.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  203.  
  204.         /* Load accumulation buffer */
  205.         rscale = value * acc_scale * ctx->Visual->InvRedScale;
  206.         gscale = value * acc_scale * ctx->Visual->InvGreenScale;
  207.         bscale = value * acc_scale * ctx->Visual->InvBlueScale;
  208.         ascale = value * acc_scale * ctx->Visual->InvAlphaScale;
  209.         for (j=0;j<height;j++) {
  210.            (*ctx->Driver.ReadColorSpan)( ctx, width, xpos, ypos,
  211.                                              red, green, blue, alpha);
  212.            acc = ctx->Buffer->Accum
  213.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  214.            for (i=0;i<width;i++) {
  215.           *acc++ = (GLaccum) ( (GLfloat) red[i]   * rscale );
  216.           *acc++ = (GLaccum) ( (GLfloat) green[i] * gscale );
  217.           *acc++ = (GLaccum) ( (GLfloat) blue[i]  * bscale );
  218.           *acc++ = (GLaccum) ( (GLfloat) alpha[i] * ascale );
  219.            }
  220.            ypos++;
  221.         }
  222.  
  223.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  224.      }
  225.      break;
  226.       case GL_RETURN:
  227.      {
  228.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  229.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  230.         GLaccum *acc;
  231.         GLfloat rscale, gscale, bscale, ascale;
  232.         GLint rmax, gmax, bmax, amax;
  233.         GLuint i, j;
  234.  
  235.         rscale = value / acc_scale * ctx->Visual->RedScale;
  236.         gscale = value / acc_scale * ctx->Visual->GreenScale;
  237.         bscale = value / acc_scale * ctx->Visual->BlueScale;
  238.         ascale = value / acc_scale * ctx->Visual->AlphaScale;
  239.         rmax = (GLint) ctx->Visual->RedScale;
  240.         gmax = (GLint) ctx->Visual->GreenScale;
  241.         bmax = (GLint) ctx->Visual->BlueScale;
  242.         amax = (GLint) ctx->Visual->AlphaScale;
  243.         for (j=0;j<height;j++) {
  244.            acc = ctx->Buffer->Accum
  245.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  246.            for (i=0;i<width;i++) {
  247.           GLint r, g, b, a;
  248.           r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
  249.           g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
  250.           b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
  251.           a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
  252.           red[i]   = CLAMP( r, 0, rmax );
  253.           green[i] = CLAMP( g, 0, gmax );
  254.           blue[i]  = CLAMP( b, 0, bmax );
  255.           alpha[i] = CLAMP( a, 0, amax );
  256.            }
  257.            (*ctx->Driver.WriteColorSpan)( ctx, width, xpos, ypos,
  258.                                               red, green, blue, alpha, NULL );
  259.            ypos++;
  260.         }
  261.      }
  262.      break;
  263.       default:
  264.          gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
  265.    }
  266. }
  267.  
  268.  
  269.  
  270.  
  271. /*
  272.  * Clear the accumulation Buffer->
  273.  */
  274. void gl_clear_accum_buffer( GLcontext *ctx )
  275. {
  276.    GLuint buffersize;
  277.    GLfloat acc_scale;
  278.  
  279.    if (ctx->Visual->AccumBits==0) {
  280.       /* No accumulation buffer! */
  281.       return;
  282.    }
  283.  
  284.    if (sizeof(GLaccum)==1) {
  285.       acc_scale = 127.0;
  286.    }
  287.    else if (sizeof(GLaccum)==2) {
  288.       acc_scale = 32767.0;
  289.    }
  290.    else {
  291.       /* sizeof(GLaccum) > 2 (Cray) */
  292.       acc_scale = (float) SHRT_MAX;
  293.    }
  294.  
  295.    /* number of pixels */
  296.    buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
  297.  
  298.    if (!ctx->Buffer->Accum) {
  299.       /* try to alloc accumulation buffer */
  300.       ctx->Buffer->Accum = (GLaccum *)
  301.                        malloc( buffersize * 4 * sizeof(GLaccum) );
  302.    }
  303.  
  304.    if (ctx->Buffer->Accum) {
  305.       if (ctx->Scissor.Enabled) {
  306.      /* Limit clear to scissor box */
  307.      GLaccum r, g, b, a;
  308.      GLint i, j;
  309.          GLint width, height;
  310.          GLaccum *row;
  311.      r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  312.      g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  313.      b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  314.      a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  315.          /* size of region to clear */
  316.          width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
  317.          height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  318.          /* ptr to first element to clear */
  319.          row = ctx->Buffer->Accum
  320.                + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
  321.                       + ctx->Buffer->Xmin);
  322.          for (j=0;j<height;j++) {
  323.             for (i=0;i<width;i+=4) {
  324.                row[i+0] = r;
  325.                row[i+1] = g;
  326.                row[i+2] = b;
  327.                row[i+3] = a;
  328.         }
  329.             row += 4 * ctx->Buffer->Width;
  330.      }
  331.       }
  332.       else {
  333.      /* clear whole buffer */
  334.      if (ctx->Accum.ClearColor[0]==0.0 &&
  335.          ctx->Accum.ClearColor[1]==0.0 &&
  336.          ctx->Accum.ClearColor[2]==0.0 &&
  337.          ctx->Accum.ClearColor[3]==0.0) {
  338.         /* Black */
  339.         MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
  340.      }
  341.      else {
  342.         /* Not black */
  343.         GLaccum *acc, r, g, b, a;
  344.         GLuint i;
  345.  
  346.         acc = ctx->Buffer->Accum;
  347.         r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  348.         g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  349.         b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  350.         a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  351.         for (i=0;i<buffersize;i++) {
  352.            *acc++ = r;
  353.            *acc++ = g;
  354.            *acc++ = b;
  355.            *acc++ = a;
  356.         }
  357.      }
  358.       }
  359.    }
  360. }
  361.